package com.sunshine.wheel.study.netty.chat.processor;

import com.sunshine.wheel.study.netty.chat.protocol.IMMessage;
import com.sunshine.wheel.study.netty.chat.protocol.IMPEnum;
import com.sunshine.wheel.study.netty.chat.util.MsgCodecUtils;
import io.netty.channel.Channel;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.json.simple.JSONObject;

/**
 * 处理自定义消息
 */
public class MsgProcessor {

    // 记录在线用户
    private static final ChannelGroup ONLINE_USERS = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    // 定义一些扩展属性
    private final AttributeKey<String> NICK_NAME = AttributeKey.valueOf("nickName");
    private final AttributeKey<String> IP_ADDR = AttributeKey.valueOf("ipAddr");
    private final AttributeKey<JSONObject> ATTRS = AttributeKey.valueOf("attrs");

    /**
     * 发送消息
     * @param channel       客户端channel
     * @param msg           即时消息
     */
    public void sendMeg(Channel channel, String msg) {
        IMMessage imMessage = MsgCodecUtils.decode(msg);
        if (IMPEnum.LOGIN.getValue().equalsIgnoreCase(imMessage.getCmd())) {
            doLoginOp(channel, imMessage);
        } else if (IMPEnum.CHAT.getValue().equalsIgnoreCase(imMessage.getCmd())) {
            doChatOp(channel, imMessage);
        }
    }

    /**
     * 处理登录时的消息发送
     * @param channel   客户端channel
     */
    private void doLoginOp(Channel channel, IMMessage imMessage) {
        channel.attr(NICK_NAME).getAndSet(imMessage.getSender());
        channel.attr(IP_ADDR).getAndSet(getAddress(channel));
        ONLINE_USERS.add(channel);

        for (Channel clientChannel : ONLINE_USERS) {
            if(channel != clientChannel){
                imMessage = new IMMessage(IMPEnum.SYSTEM.getValue(), getSysTime(), ONLINE_USERS.size(), getNickName(clientChannel) + "加入");
            }else{
                imMessage = new IMMessage(IMPEnum.SYSTEM.getValue(), getSysTime(), ONLINE_USERS.size(), "已与服务器建立连接！");
            }
            String content = MsgCodecUtils.encode(imMessage);
            System.out.println("login = " + content);
            channel.writeAndFlush(new TextWebSocketFrame(content));
        }
    }

    /**
     * 处理聊天时的消息发送
     * @param channel   客户端channel
     */
    private void doChatOp(Channel channel, IMMessage imMessage) {
        for (Channel clientChannel : ONLINE_USERS) {
            if (channel == clientChannel) {
                imMessage.setSender("you");
            }else{
                imMessage.setSender(getNickName(clientChannel));
            }
            imMessage.setTime(getSysTime());
            String content = MsgCodecUtils.encode(imMessage);
            channel.writeAndFlush(new TextWebSocketFrame(content));
        }
    }

    /**
     * 处理送花时的消息发送
     * @param channel   客户端channel
     */
    private static void doFlowerOp(Channel channel) {

    }

    /**
     * 获取用户远程IP地址
     * @param channel   客户端channel
     * @return
     */
    public String getAddress(Channel channel){
        return channel.remoteAddress().toString().replaceFirst("/","");
    }

    /**
     * 获取当前系统时间
     * @return
     */
    public Long getSysTime() {
        return System.currentTimeMillis();
    }

    /**
     * 获取用户昵称
     * @param channel
     * @return
     */
    public String getNickName(Channel channel){
        return channel.attr(NICK_NAME).get();
    }

    /**
     * 登出
     * @param channel   客户端channel
     */
    public void logout(Channel channel) {
        // 如果nickName为null，没有遵从聊天协议的连接，表示未非法登录
        if(getNickName(channel) == null){ return; }
        for (Channel clientChannel : ONLINE_USERS) {
            IMMessage request = new IMMessage(IMPEnum.SYSTEM.getValue(), getSysTime(), ONLINE_USERS.size(), getNickName(clientChannel) + "离开");
            String content = MsgCodecUtils.encode(request);
            channel.writeAndFlush(new TextWebSocketFrame(content));
        }
        ONLINE_USERS.remove(channel);
    }
}
